﻿using System.Collections.Generic;

#if UNITY_EDITOR
using System;
using System.Reflection;
using com.yoozoo.gta.Extension.UGUI.ScreenOrientation.Adapter;
using com.yoozoo.gta.Tools.UI;
using UnityEngine.SceneManagement;
using Yoozoo.Gta.Common;
using Yoozoo.UI.YGUI;
using UnityEditor.SceneManagement;
using UnityEditor;
using UnityEngine.UI;
#endif

using UnityEngine;
using XLua;

namespace com.yoozoo.gta.Extension.UGUI.ScreenOrientationEx
{
    /// <summary>
    /// 添加到UI的根节点上，负责管理所有的Adapter组件，以及监听横竖屏变化
    /// 该类对象会被工具自动添加，不要手动添加（非UI需要手动处理下)
    /// </summary>
    ///
    [DisallowMultipleComponent][ExecuteAlways]
    public class ScreenOrientItem : MonoBehaviour
    {
        public List<ScreenOrientationChangeHandler> ChangeHandlersList = new List<ScreenOrientationChangeHandler>();
        private bool isRegister = false;
        public string Name => this.gameObject.name;

        public void RegisterAllListener(bool needForceApply = false)
        {
            if (isRegister)
            {
                //UnityEngine.Debug.LogWarningFormat("{0}重复Register,请检查",this.gameObject.name);
                return;
            }

            var sodInstance = ScreenOrientManager.GetInstance();
            if (sodInstance == null)
            {
                //UnityEngine.Debug.LogError("ScreenOrientDetector未初始化，请检查");
                return;
            }

            int count = ChangeHandlersList.Count;
            for (int i = 0; i < count; i++)
            {
                if (ChangeHandlersList[i])
                {
                    sodInstance.AddOrientationChangeListener(ChangeHandlersList[i], needForceApply);
                }
                else
                {
#if UNITY_EDITOR
                    Debug.LogWarningFormat("ChangeHandlersList[{0}] is null, count = {1}, gameObject = {2}", 
                        i, count, gameObject.name);
#endif
                }
            }

            isRegister = true;
        }

        public void UnRegisterAllListener()
        {
            isRegister = false;
            int count = ChangeHandlersList.Count;
            for (int i = 0; i < count; i++)
            {
                if (ChangeHandlersList[i])
                {
                    ScreenOrientManager.GetInstance().RemoveOrientationChangeListener(ChangeHandlersList[i]);
                }
                //else
                //{
                  //  Debug.LogWarningFormat("ChangeHandlersList[i] is null,请检查 {0}",this.gameObject.name);
                //}

                
            }

           
        }
        public void Awake()
        {
            if (!isRegister)
            {
                RegisterAllListener(true);
            }
        }
        public void OnEnable()
        {
            if (!isRegister)
            {
                RegisterAllListener();
            }
        }
        public void OnDisable()
        {
            if (isRegister)
            {
                UnRegisterAllListener();
            }
        }
        public void OnDestroy()
        {
            if (isRegister)
            {
                UnRegisterAllListener();
            }
        }
 
#if UNITY_EDITOR
        [BlackList]
        private void OnValidate()
        {

            return;
            //OnValidate方法在编辑器模式下，当脚本组件的属性发生变化时，会被调用
            
            if (EditorApplication.isCompiling)
            {
                //UnityEngine.Debug.LogWarning("Unity编辑器---Compiling.......");
                return;
            }
            
            if(EditorApplication.isPlayingOrWillChangePlaymode || ScreenOrientManager.GetInstance().EditorChangePlayMode)
            {
               // UnityEngine.Debug.LogWarning("Unity编辑器---isPlayingOrWillChangePlaymode.......");
                return;
            }
            bool isInPrefabStage = IsEditingInPrefabStage();
            if (this.gameObject.scene == SceneManager.GetActiveScene() )
            {
                if (!isInPrefabStage)
                {
                    UnityEngine.Debug.LogWarningFormat("[OnValidate]---ScreenOriientItem : {0}====================",GetGameObjectPath(this.gameObject));
                    RefreshCollectUsedListener();
                }
            }
            else 
            {
                if (isInPrefabStage)
                {
                    var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
                    if(prefabStage.openedFromInstanceObject == this.gameObject)
                    {
                        UnityEngine.Debug.LogWarningFormat("[OnValidate]---ScreenOriientItem : {0}====================",GetGameObjectPath(this.gameObject));
                        UnityEngine.Debug.Log(this.name + " is in the Prefab Stage."); 
                        RefreshCollectUsedListener();
                    }
                }
            }
        }

        private bool IsEditingInPrefabStage()
        {
            var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
            return prefabStage != null;
        }
        /// <summary>
        /// 工具方法，初始化所有的Adapter组件
        /// </summary>
        [BlackList]
        public void InitAllAdapter()
        {

            if (Application.isPlaying)
            {
                return;
            }
            //给所有空的添加Adapter组件
            
            //遍历该节点下的所有gameobject，以及子节点，包含隐藏的
            var allTransforms = GetComponentsInChildren(typeof(Transform), true); 
            foreach (var transform in allTransforms)
            {
                if (isCurrentScreenOrientItemChild(transform))
                {
                      AddNeedAdapterToGameObject(transform as Transform,this);
                      RemoveUnNeedAdapterFormGameObject(transform as Transform,this);//删除无用的Adapter
                }
                
            }
            
            
        }
        private static Dictionary<Type,Type> ComponentTypeToAdapterType = new Dictionary<Type, Type>();
        
        [BlackList]
        public static bool CleanUpByHand { get; set; }
        
        [BlackList]
        public static  void AddNeedAdapterToGameObject(Transform targetTransform,ScreenOrientItem screenOrientItem)
        {
            if (ComponentTypeToAdapterType.Count == 0)
            {
                initAdapter2ComponentType();
            }
            
            Component[] newComponents = targetTransform.gameObject.GetComponents<Component>();
            foreach (var component in newComponents)
            {
                var componentType = component.GetType();
                if(ComponentTypeToAdapterType.TryGetValue(componentType, out var adapterType))
                {
                    if (!targetTransform.gameObject.GetComponent(adapterType))
                    {
                        
                        if(componentType == typeof(RectTransform) && IsNeedIgnoreRectTransformAdapter(component) )
                        {
                            continue;
                        }
                        if((componentType == typeof(VerticalLayoutGroup) || componentType == typeof(HorizontalLayoutGroup)) && IsNeedIgnoreLayoutGroupAdapter(component) )
                        {
                            continue;
                        }
                        if (!targetTransform.gameObject.GetComponent(adapterType))
                        {
                            var adapterComponent = targetTransform.gameObject.AddComponent(adapterType);
                            screenOrientItem.ChangeHandlersList.Add(adapterComponent as ScreenOrientationChangeHandler);
                        }
                    }
                }
            }
        }
        
        [BlackList]
        public static void RemoveUnNeedAdapterFormGameObject(Transform targetTransform,ScreenOrientItem screenOrientItem)
        {
            if (ComponentTypeToAdapterType.Count == 0)
            {
                initAdapter2ComponentType();
            }
            Component[] newComponents = targetTransform.gameObject.GetComponents<Component>();
            foreach (var component in newComponents)
            {
                var componentType = component.GetType();
                if(componentType.BaseType != null && componentType.BaseType.IsGenericType &&  
                   componentType.BaseType.GetGenericTypeDefinition() == typeof(AdaptBase<,>))
                {
                    var genericArguments = componentType.BaseType.GetGenericArguments();
                    if (genericArguments.Length > 1)
                    {
                        var it = genericArguments[1];
                        if (targetTransform.gameObject.GetComponent(it) == null)
                        {
                            UnityEngine.Debug.LogFormat("RemoveUnNeedAdapterFormGameObject: {0}",componentType);
                            GameObject.DestroyImmediate(component);
                        }
                    }
                    else
                    {
                        Debug.LogErrorFormat("未知Adapter类型 :{0}",componentType);
                    }
                }
                
            }
        }

        private static void initAdapter2ComponentType()
        {
            var types = Assembly.GetExecutingAssembly().GetTypes();
            foreach (var type in types)
            {
                if (type.BaseType != null && type.BaseType.IsGenericType &&
                    type.BaseType.GetGenericTypeDefinition() == typeof(AdaptBase<,>))
                {

                    var adapterType = type;
                    var genericArguments = adapterType.BaseType.GetGenericArguments();
                    if (genericArguments.Length > 1)
                    {
                        var componentType = genericArguments[1];
                        if (!ComponentTypeToAdapterType.TryAdd(componentType, adapterType))
                        {
                            Debug.LogErrorFormat("Adapter2ComponentType添加失败:{0}",componentType);
                        }
                    }
                    else
                    {
                        Debug.LogErrorFormat("未知Adapter类型 :{0}",type);
                    }
                } 
            }
        }
        [BlackList]
        public static bool IsNeedIgnoreLayoutGroupAdapter(Component component)
        {
            var yList = component.GetComponent<YList>();
           
            
            if(yList != null)
            {
                return true;
            }
            var yTable = component.name == "Content" && component.GetComponentInParent<YTableView>() != null;
            if (yTable)
            {
                return true;
            }
            return false;

        }
        [BlackList]
        public static bool IsNeedIgnoreRectTransformAdapter(Component component)
        {
            if(component.GetComponent<ContentSizeFitter>() != null)
            {
                return true;
            }
            return isListViewChild(component) || isLayoutChild(component) || isMarginScaler(component);
        }

        [BlackList]
        public  bool isCurrentScreenOrientItemChild(Component component)
        {
            var parent = component.transform;
            while (parent != null)
            {
                if (parent.GetComponent<ScreenOrientItem>())
                {
                    if (parent == this.transform)
                    {
                        return true;
                    }

                    {
                        return false;
                    }
                }


                parent = parent.parent;
            }
            return false;

        }

 
        private static bool isListViewChild(Component component)
        {
            if (component.gameObject.name == "Content" && component.transform.parent.name == "Viewport")
            {
                return true;
            }

            if (component.transform.GetComponent<ListViewItem>() != null)
            {
                return true;
            }

            return false;
        }
        
        private static bool isLayoutChild(Component component)
        {
            if (component.transform.parent!=null)
            {
                var layoutGroup = component.transform.parent.GetComponent<HorizontalOrVerticalLayoutGroup>();
                if( null != layoutGroup && (layoutGroup.childControlHeight || layoutGroup.childControlWidth))
                {
                    return true;
                }
            }
            //这里没办法判断，默认有LayoutElement的就不自动生成RectTransform
            if (component.transform.GetComponent<LayoutElement>())
            {
                return true;
            }
            return false;
        }
 
        private static bool isMarginScaler(Component component)
        {
            if (component.transform.GetComponent<MarginScaler>())
            {
                return true;
            }
            return false;
        }
        
        private static bool isFullImageScaler(Component component)
        {
            if (component.transform.GetComponent<FullImageScaler>())
            {
                return true;
            }
            return false;
        }
        
        [BlackList]
        public void CleanUpAdapter(bool force = false)
        {
            
            if (Application.isPlaying)
            {
                return;
            }
            //先清理掉所有注册监听
            UnRegisterAllListener();
            //重新收集
            ChangeHandlersList.Clear();
            UnityEngine.Debug.Log("==================清理无用Adapter====================");
            //当横竖屏属性一致，认为是不需要的Adapter组件
            var allChangeHandlers = GetComponentsInChildren<ScreenOrientationChangeHandler>(true); //包含隐藏的
            foreach (var adpaterHandler in allChangeHandlers)
            {
                try
                {
                    if (isCurrentScreenOrientItemChild(adpaterHandler))
                    {
                        if (adpaterHandler.IsCanCleanup() || force)
                        {
                            UnityEngine.Debug.LogFormat("Destroy Adapter: gameObjectName={0},  componentName={1} ",
                                adpaterHandler.gameObject.name, adpaterHandler.GetType().Name);
                            GameObject.DestroyImmediate(adpaterHandler,true);
                        }
                        else
                        {
                            ChangeHandlersList.Add(adpaterHandler);
                        }
                    }
                }catch (Exception e)
                {
                    UnityEngine.Debug.LogErrorFormat("清理Adapter失败:{0}",e);
                }
           
            }
        }
        [BlackList]
        public void ClearNoneAdapter()
        {
            int count = ChangeHandlersList.Count;
            for (int i = count-1; i > -1; i--)
            {
                if (ChangeHandlersList[i] != null)
                {
                    if (ChangeHandlersList[i].HasComponent() == false)
                    {
                        ChangeHandlersList.RemoveAt(i);
                        Debug.LogWarning("清理掉无用的Listener");
                    }else if(isLayoutChild(ChangeHandlersList[i].transform) || isListViewChild(ChangeHandlersList[i].transform) || isMarginScaler(ChangeHandlersList[i].transform))
                    {
                        ChangeHandlersList.RemoveAt(i);
                        Debug.LogWarning("清理掉无用的Listener");
                    }
                   
                }
                else
                {
                    ChangeHandlersList.RemoveAt(i);
                }
            }
        }
        //关闭prefab时，用横版配置刷新下prefab，以避免提交时不必要的冲突
        [BlackList]
        public void ResetToLandscape()
        {
            if (Application.isPlaying)
            {
                return;
            }
            
            foreach (var adpaterHandler in ChangeHandlersList)
            {
                adpaterHandler.ApplyLandscapeConfig();
                if (adpaterHandler is YImageAdapter)
                {
                    var yImageAdapter = adpaterHandler as YImageAdapter;
                    if (!yImageAdapter.IsCanCleanup())
                    {
                        var yButton = yImageAdapter.transform.GetComponent<YButton>();
                        var yImage = yImageAdapter.GetComponent();
                        if (yImage!=null && yButton && (yButton.targetGraphic!=null && yButton.targetGraphic.gameObject == yImage.gameObject))  //YButton的targetGraphic是YImage
                        {
                            continue;
                        }

                        yImageAdapter.ClearYImage();

                    }
                }
            }
        }
        [BlackList]
        public void SetInvalid()
        {
            if (Application.isPlaying)
            {
                return;
            }
            
            foreach (var adpaterHandler in ChangeHandlersList)
            {
                adpaterHandler.SetInvalid();
            }
        }
        [BlackList]
        public void RefreshCollectUsedListener()
        {
            // if (Application.isPlaying)
            // {
            //     return;
            // }
            
            //先清理掉所有注册监听
            UnRegisterAllListener();
            
            ChangeHandlersList.Clear();
            UnityEngine.Debug.LogFormat("==================RefreshCurrentUseListener  {0}====================",GetGameObjectPath(this.gameObject));
            //当横竖屏属性一致，认为是不需要的Adapter组件
            var allChangeHandlers = GetComponentsInChildren<ScreenOrientationChangeHandler>(true); //包含隐藏的
            foreach (var adpaterHandler in allChangeHandlers)
            {

                if (isCurrentScreenOrientItemChild(adpaterHandler))
                {
                    
                    ChangeHandlersList.Add(adpaterHandler);
                }
            }
            
            RegisterAllListener();
            
        }
        
        [BlackList]
        public void CollectUsedListener()
        {
           
            ChangeHandlersList.Clear();
            UnityEngine.Debug.LogFormat("==================CollectUsedListener  {0}====================",GetGameObjectPath(this.gameObject));
            //当横竖屏属性一致，认为是不需要的Adapter组件
            var allChangeHandlers = GetComponentsInChildren<ScreenOrientationChangeHandler>(true); //包含隐藏的
            foreach (var adpaterHandler in allChangeHandlers)
            {

                if (isCurrentScreenOrientItemChild(adpaterHandler))
                {
                    
                    ChangeHandlersList.Add(adpaterHandler);
                }
            }
        }
        [BlackList]  
        public string GetGameObjectPath(GameObject obj)
        {
            string path = obj.scene.name+"/" + obj.name;
            while (obj.transform.parent != null)
            {
                obj = obj.transform.parent.gameObject;
                path = "/" + obj.name + path;
            }
            return path;
        }
        [BlackList]
        public bool SaveConfigData()
        {
            var allChangeHandlers = GetComponentsInChildren<ScreenOrientationChangeHandler>(true); //包含隐藏的
            bool success = true;
            foreach (var adpaterHandler in allChangeHandlers)
            {
                //if (isCurrentScreenOrientItemChild(adpaterHandler))
                {
                  var result =  adpaterHandler.SaveConfigData();
                  if (!result)
                  {
                      UnityEngine.Debug.LogErrorFormat("{0}保存配置失败，请检查",adpaterHandler.gameObject.name);
                      success = false;
                  }
                }
            }

            return success;
        }
#endif
        
    }
}